﻿
#region Usings

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;

#endregion

namespace FasterWPF
{
    #region ISortArgs

    public class StackPanelSort : FasterWPF.CommonExt.ISortArgs
    {
        public StackPanelSort(CommonExt.SortDataType sortDataType)
        {
            SortDataType = sortDataType;
        }

        public StackPanelSort(CommonExt.SortDataType sortDataType, CommonExt.SortDataType sortDataType2)
        {
            SortDataType = sortDataType;
            SortDataType2 = sortDataType2;
        }

        public CommonExt.SortDataType SortDataType
        {
            get;
            set;
        }

        public CommonExt.SortDataType SortDataType2
        {
            get;
            set;
        }
    }

    #endregion

    public class StackPanelArgs
    {
        public Orientation Orientation { get; set; }

        public StackPanelArgs(Orientation orientation)
        {
            Orientation = orientation;
        }
    }

    public class StackPanelParent : FasterWPF.IParent, ICanSort, FasterWPF.IScrollViewerStrategy
    {         
        //this is ANA?
        public object Generate<T>(object chain, T args, Action<ContentControl> addUIElementsAction)
        {
            return chain;
        }

        #region IParent

        //this is BIND
        public object Add<T>(object chain, string key, T args, Border itemToAdd)
        {
            if (args is StackPanelArgs)
            {
                if ((args as StackPanelArgs).Orientation != null)
                {
                    ((StackPanel)chain).Orientation = (args as StackPanelArgs).Orientation;
                }
            }

            ((StackPanel)chain).Children.Add(itemToAdd);
            return chain;
        }

        public void Remove(object chain, string key, Border itemToRemove)
        {
            ((StackPanel)chain).Children.Remove(itemToRemove); //remove from Window

            IComposite ic = (IComposite)(((StackPanel)chain).GetIComposite<StackPanel>());
            ic.RemoveFromChain(itemToRemove);
        }

        public Dictionary<string, object> RetrieveDictionary(object chain)
        {
            return ((StackPanel)chain).GetCompositeLookupDictionary<StackPanel>();
        }
        
        //this is CATA?
        public List<Border> RetrieveCollection(object chain)
        {
            List<Border> lb = new List<Border>();
            foreach (var kvp in ((StackPanel)chain).GetCompositeLookupDictionary<StackPanel>())
            {
                lb.Add((Border)kvp.Value);
            }

            return lb;
        }

        #endregion

        #region ICanSort

        public void ClearCollection(object chain)
        {
            IParent currentComposite = ((StackPanel)chain).GetSetting<StackPanel, IParent>("IParent");
            List<Border> gridItems = currentComposite.RetrieveCollection(chain);

            foreach (Border borItem in gridItems)
            {
                ((StackPanel)chain).Children.Remove(borItem); //remove from Grid
            }
        }

        public void BeforeSortCollection<T>(object chain, object args, int row, int column, CommonExt.SortOrder sortOrder, CommonExt.SortControlType sortControlType) where T : FrameworkElement
        {
            var orderedKeys = ((StackPanel)chain).GetOrderedKeyList();
            var rows = ((StackPanel)chain).GetCompositeLookupDictionary();
            Dictionary<string, object> ChildLookupDict = ((StackPanel)chain).GetChildLookupDictionary();

            IParent currentComposite = ((StackPanel)chain).GetSetting<StackPanel, IParent>("IParent");
            List<Border> gridItemsUnOrdered = currentComposite.RetrieveCollection(chain);
            List<Border> gridItems = new List<Border>();
            foreach (string s in orderedKeys)
            {
                gridItems.Add(gridItemsUnOrdered.Where(b => { return b.GetKey() == s; }).First());
            }

            List<int> initialOrderCol = new List<int>();
            List<int> initialOrderRow = new List<int>();
            List<string> initialOrderKey = new List<string>();

            foreach (Border borK in gridItems)
            {
                initialOrderKey.Add(borK.GetKey());
            }

            if (gridItems != null && gridItems.Count > 0)
            {
                ClearCollection(chain);

                orderedKeys.Clear();

                IEnumerable<string> items = null;

                if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.DateTime)
                {
                    items = CommonInternalExt.PerformSortOfKeysLevelOneDateTime<T>(row, column, sortOrder, ChildLookupDict, items, sortControlType);
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.Decimal)
                {
                    items = CommonInternalExt.PerformSortOfKeysLevelOneDecimal<T>(row, column, sortOrder, ChildLookupDict, items, sortControlType);
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.Integer)
                {
                    items = CommonInternalExt.PerformSortOfKeysLevelOneInteger<T>(row, column, sortOrder, ChildLookupDict, items, sortControlType);
                }
                else
                {
                    //Default to String
                    items = CommonInternalExt.PerformSortOfKeysLevelOne<T>(row, column, sortOrder, ChildLookupDict, items, sortControlType);
                }

                List<string> itemsToList = items.ToList();

                IterHelpers.ApplyLoop(itemsToList.Count, j =>
                {
                    String tempKey = (string)itemsToList[j];
                    Border tempBorder = gridItems[initialOrderKey.FindIndex(str => { return str == tempKey; })];
                    orderedKeys.Add(tempKey);

                    ((StackPanel)chain).Children.Add(tempBorder);
                });
            }
        }

        public void BeforeSortCollection1Then2<T>(object chain, object args, int row, int column, int row2, int column2, CommonExt.SortOrder sortOrder, CommonExt.SortOrder sortOrder2, CommonExt.SortControlType sortControlType) where T : FrameworkElement
        {
            var orderedKeys = ((T)chain).GetOrderedKeyList();
            var rows = ((T)chain).GetCompositeLookupDictionary();
            Dictionary<string, object> ChildLookupDict = ((T)chain).GetChildLookupDictionary();

            IParent currentComposite = ((T)chain).GetSetting<T, IParent>("IParent");
            List<Border> gridItemsUnOrdered = currentComposite.RetrieveCollection(chain);
            List<Border> gridItems = new List<Border>();
            foreach (string s in orderedKeys)
            {
                gridItems.Add(gridItemsUnOrdered.Where(b => { return b.GetKey() == s; }).First());
            }

            List<string> initialOrderKey = new List<string>();

            foreach (Border borK in gridItems)
            {
                initialOrderKey.Add(borK.GetKey());
            }

            if (gridItems != null && gridItems.Count > 0)
            {
                ClearCollection(chain);

                Dictionary<string, Tuple<object, object>> sourceToSortOn = new Dictionary<string, Tuple<object, object>>();

                string defaultNullValue = null;
                string defaultNullValue2 = null;

                if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.DateTime)
                {
                    defaultNullValue = "1/1/1900";
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.Decimal)
                {
                    defaultNullValue = "0.00";
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.Integer)
                {
                    defaultNullValue = "0";
                }
                else
                {
                    defaultNullValue = "";
                }

                if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType2) == FasterWPF.CommonExt.SortDataType.DateTime)
                {
                    defaultNullValue2 = "1/1/1900";
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType2) == FasterWPF.CommonExt.SortDataType.Decimal)
                {
                    defaultNullValue2 = "0.00";
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType2) == FasterWPF.CommonExt.SortDataType.Integer)
                {
                    defaultNullValue2 = "0";
                }
                else
                {
                    defaultNullValue2 = "";
                }

                CommonInternalExt.SetDefaultsForTextElementsAtRowCol<T>(chain, row, column, row2, column2, sortControlType, orderedKeys, sourceToSortOn, defaultNullValue, defaultNullValue2);

                orderedKeys.Clear();

                IOrderedEnumerable<KeyValuePair<string, Tuple<object, object>>> items = null;

                Type dataType1 = null;
                Type dataType2 = null;

                if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.DateTime)
                {
                    dataType1 = typeof(DateTime);
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.Decimal)
                {
                    dataType1 = typeof(Decimal);
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType) == FasterWPF.CommonExt.SortDataType.Integer)
                {
                    dataType1 = typeof(Int32);
                }
                else
                {
                    dataType1 = typeof(String);
                }

                if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType2) == FasterWPF.CommonExt.SortDataType.DateTime)
                {
                    dataType2 = typeof(DateTime);
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType2) == FasterWPF.CommonExt.SortDataType.Decimal)
                {
                    dataType2 = typeof(Decimal);
                }
                else if (args is FasterWPF.CommonExt.ISortArgs && (((FasterWPF.CommonExt.ISortArgs)args).SortDataType2) == FasterWPF.CommonExt.SortDataType.Integer)
                {
                    dataType2 = typeof(Int32);
                }
                else
                {
                    dataType2 = typeof(String);
                }

                items = CommonInternalExt.PerformSortOfKeysLevelTwo(chain, sortOrder, sortOrder2, sourceToSortOn, items, dataType1, dataType2);

                List<KeyValuePair<string, Tuple<object, object>>> itemsToList = items.ToList();

                IterHelpers.ApplyLoop(itemsToList.Count, j =>
                {
                    String tempKey = ((KeyValuePair<string, Tuple<object, object>>)itemsToList[j]).Key.ToString();
                    Border tempBorder = gridItems[initialOrderKey.FindIndex(str => { return str == tempKey; })];
                    orderedKeys.Add(tempKey);

                    ((StackPanel)chain).Children.Add(tempBorder);
                });
            }    
        }

        public void AfterSortCollection<T>(object chain)
             where T : FrameworkElement
        { }

        public void InnerSortCollection(object chain, int row, int column, string key, ref int counter, Border itemToReAdd)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region ICanSelect

        public void SetSelected(object chain, Border itemToSetAsSelected)
        {
        }

        #endregion

        //public void GetSelected
        //    return (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(grid.SelectedItem);

        #region IScrollViewerStrategy

        public ScrollViewer GetScrollViewer(object chain)
        {
            StackPanel lbx = (StackPanel)chain;
           // var builtCheck = lbx.ApplyTemplate();
           // Border bd = (Border)lbx.Template.FindName("Bd", lbx);

            var settings = lbx.GetSettingsDictionary();

            if (settings.Keys.Contains("ScrollViewerPadding"))
            {
                ((Border) lbx.ScrollOwner.Parent).Padding = (Thickness)settings["ScrollViewerPadding"];
            }
            else
            {
                ((Border) lbx.ScrollOwner.Parent).Padding = new Thickness(0); //default to zero
            }
            ScrollViewer svw = lbx.ScrollOwner; //bd.Child.Cast<ScrollViewer>();

            return svw;
        }

        public T GetParentContainerFromScrollViewerThumb<T>(System.Windows.Controls.Primitives.Thumb myThumb)
        {
            T source = ((Border)((ScrollViewer)
                ((Grid)
                ((ScrollBar)myThumb.TemplatedParent).Parent).TemplatedParent
                ).Parent).TemplatedParent.Cast<T>();
            return source;
        }

        #endregion       

    }
}
